package com.egao.common.module.student.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.minio.config.MinioBucket;
import com.egao.common.component.minio.service.MinioService;
import com.egao.common.core.Constants;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.exception.ParameterException;
import com.egao.common.core.utils.ExcelUtils;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.module.student.constants.*;
import com.egao.common.module.student.entity.*;
import com.egao.common.module.student.entity.excel.StudentStatusExcel;
import com.egao.common.module.student.entity.vo.*;
import com.egao.common.module.student.mapper.StudentMapper;
import com.egao.common.module.student.mapper.StudentResumeItemMapper;
import com.egao.common.module.student.service.*;
import com.egao.common.module.system.constants.DictConstants;
import com.egao.common.module.system.entity.Dict;
import com.egao.common.module.system.entity.User;
import com.egao.common.module.system.entity.Year;
import com.egao.common.module.system.mapper.UserMapper;
import com.egao.common.module.system.service.DictService;
import com.egao.common.module.system.service.MajorService;
import com.egao.common.module.system.service.UserService;
import com.egao.common.module.system.service.YearService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学生服务接口实现类
 *
 * @author lym
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Autowired
    private StudentInfoService studentInfoService;
    @Autowired
    private DictService dictService;
    @Autowired
    private StudentRecordService studentRecordService;
    @Autowired
    private YearService yearService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StudentResumeService studentResumeService;
    @Autowired
    private MajorService majorService;
    @Autowired
    private StudentResumeItemMapper studentResumeItemMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private StudentIntenService studentIntenService;
    @Autowired
    private MinioService minioService;


    private final Logger logger = LoggerFactory.getLogger(StudentServiceImpl.class.getName());

    @Override
    public List<StudentListVO> listPage(PageParam<StudentListVO> page) {
        page.setDefaultOrder(new String[]{"college_code"}, null);
        return baseMapper.listPage(page);
    }

    @Override
    public Student getByUserId(Integer userId) {
        return baseMapper.selectOne(new QueryWrapper<Student>().eq("user_id", userId).last("limit 1"));
    }

    @Override
    public Student getByXh(String xh) {
        return baseMapper.selectOne(new QueryWrapper<Student>().eq("xh", xh).last("limit 1"));
    }

    @Override
    public StudentFormVO getStudentFormVO(Integer id) {
        if (id == null) {
            throw new ParameterException("参数异常");
        }

        StudentFormVO studentFormVO = baseMapper.getDetail(id);

        if (studentFormVO == null) {
            throw new BusinessException("学生信息异常");
        }

        studentFormVO.setXbLabel(dictService.cacheLabel(DictConstants.TYPE_XB, studentFormVO.getXb()));
        studentFormVO.setXlLabel(dictService.cacheLabel(DictConstants.TYPE_XL, studentFormVO.getXl()));
        studentFormVO.setXwLabel(dictService.cacheLabel(DictConstants.TYPE_XW, studentFormVO.getXw()));
        studentFormVO.setXwlbLabel(dictService.cacheLabel(DictConstants.TYPE_XWLB, studentFormVO.getXwlb()));
        studentFormVO.setPyfsLabel(dictService.cacheLabel(DictConstants.TYPE_PYFS, studentFormVO.getPyfs()));
        studentFormVO.setCxsydmLabel(dictService.cacheLabel(DictConstants.TYPE_CXSYDM, studentFormVO.getCxsydm()));
        studentFormVO.setXxfsLabel(dictService.cacheLabel(DictConstants.TYPE_XXFS, studentFormVO.getXxfs()));
        studentFormVO.setSyszdLabel(dictService.cacheLabel(DictConstants.TYPE_SYSZD, studentFormVO.getSyszd()));
        studentFormVO.setZxjhLabel(dictService.cacheLabel(DictConstants.TYPE_ZXJH, studentFormVO.getZxjh()));
        studentFormVO.setXjztLabel(dictService.cacheLabel(DictConstants.TYPE_XJZT, studentFormVO.getXjzt()));
        studentFormVO.setJzbfdxbzLabel(dictService.cacheLabel(DictConstants.TYPE_JZBFDXBZ, studentFormVO.getJzbfdxbz()));
        studentFormVO.setKnslbLabel(dictService.cacheLabel(DictConstants.TYPE_KNSLB, studentFormVO.getKnslb()));
        studentFormVO.setZzmmLabel(dictService.cacheLabel(DictConstants.TYPE_ZZMM, studentFormVO.getZzmm()));
        studentFormVO.setDxDwszdLabel(dictService.cacheLabel(DictConstants.TYPE_SYSZD, studentFormVO.getDxDwszd()));
        studentFormVO.setDxDwxzLabel(dictService.cacheLabel(DictConstants.COMPANY_NATURE, studentFormVO.getDxDwxz()));
        studentFormVO.setDxDwhyLabel(dictService.cacheLabel(DictConstants.COMPANY_INDUSTRY, studentFormVO.getDxDwhy()));
        studentFormVO.setHksfzrxxLabel(dictService.cacheLabel(DictConstants.TYPE_HKSFZRXX, studentFormVO.getHksfzrxx()));
        studentFormVO.setMzLabel(dictService.cacheLabel(DictConstants.TYPE_MZ, studentFormVO.getMz()));
        studentFormVO.setHyzkLabel(dictService.cacheLabel(DictConstants.TYPE_HYZK, studentFormVO.getHyzk()));
        studentFormVO.setFxxwLabel(dictService.cacheLabel(DictConstants.TYPE_FXXW, studentFormVO.getFxxw()));
        studentFormVO.setZxwyyzLabel(dictService.cacheLabel(DictConstants.TYPE_ZXWYYZ, studentFormVO.getZxwyyz()));
        studentFormVO.setBzkxlLabel(dictService.cacheLabel(DictConstants.TYPE_BZKXL, studentFormVO.getBzkxl()));
        studentFormVO.setBzkccLabel(dictService.cacheLabel(DictConstants.TYPE_BZKCC, studentFormVO.getBzkcc()));
        studentFormVO.setYxdqLabel(dictService.cacheLabel(DictConstants.TYPE_SYSZD, studentFormVO.getYxdq()));
        studentFormVO.setYxdwxzLabel(dictService.cacheLabel(DictConstants.TYPE_YXDWXZ, studentFormVO.getYxdwxz()));
        studentFormVO.setYxdwhyLabel(dictService.cacheLabel(DictConstants.TYPE_YXDWHY, studentFormVO.getYxdwhy()));
        studentFormVO.setYxzwlbLabel(dictService.cacheLabel(DictConstants.TYPE_YXZWLB, studentFormVO.getYxzwlb()));
        studentFormVO.setYxyxLabel(dictService.cacheLabel(DictConstants.TYPE_YXYX, studentFormVO.getYxyx()));



        studentFormVO.setPyfsDictList(dictService.cacheList(DictConstants.TYPE_PYFS));
        studentFormVO.setSyszdDictList(dictService.cacheList(DictConstants.TYPE_SYSZD));
        studentFormVO.setZxjhDictList(dictService.cacheList(DictConstants.TYPE_ZXJH));
        studentFormVO.setKnslbDictList(dictService.cacheList(DictConstants.TYPE_KNSLB));
        studentFormVO.setZzmmDictList(dictService.cacheList(DictConstants.TYPE_ZZMM));
        studentFormVO.setMzDictList(dictService.cacheList(DictConstants.TYPE_MZ));
        studentFormVO.setZxwyyzDictList(dictService.cacheList(DictConstants.TYPE_ZXWYYZ));

        studentFormVO.setCompanyNatureDictList(dictService.cacheList(DictConstants.COMPANY_NATURE));
        studentFormVO.setCompanyIndustryDictList(dictService.cacheList(DictConstants.COMPANY_INDUSTRY));

        studentFormVO.setYxdwxzDictList(dictService.cacheList(DictConstants.TYPE_YXDWXZ));
        studentFormVO.setYxdwhyDictList(dictService.cacheList(DictConstants.TYPE_YXDWHY));
        studentFormVO.setYxzwlbDictList(dictService.cacheList(DictConstants.TYPE_YXZWLB));
        studentFormVO.setYxyxDictList(dictService.cacheList(DictConstants.TYPE_YXYX));

        return studentFormVO;
    }

    @Override
    public JsonResult delay(StudentFormVO studentFormVO, Integer userId) {
        if (studentFormVO == null) {
            throw new BusinessException("参数异常");
        }

        Student student = getById(studentFormVO.getId());

        if (student == null) {
            throw new BusinessException("没有找到学生信息");
        }

        if (student.getYearId() == null) {
            throw new BusinessException("没有找到学生毕业年份信息");
        }

        Integer oldYear = student.getYearId();
        Integer newYear = oldYear + 1;

        Year year = yearService.getById(newYear);

        if (year == null) {
            throw new BusinessException("目前系统内还没有'" + newYear + "'年的毕业年份，请先在毕业年份管理中新增年份后再来操作");
        }

        student.setDelayState(StudentConstants.STUDENT_DELAY_TRUE);
        student.setYearId(newYear);
        baseMapper.updateById(student);

        StudentRecord studentRecord = new StudentRecord(userId, student.getId(), StudentConstants.RECORD_TYPE_STUDENT, StudentConstants.RECORD_OPERATE_DELAY + "：" + oldYear + "-" + newYear, studentFormVO.getSchoolContent());
        studentRecordService.save(studentRecord);

        return JsonResult.ok();
    }

    @Override
    public JsonResult unlock(StudentFormVO studentFormVO, Integer userId) {
        if (studentFormVO == null) {
            throw new BusinessException("参数异常");
        }

        Student student = getById(studentFormVO.getId());

        if (student == null) {
            throw new BusinessException("没有找到学生信息");
        }

        student.setDirectionalState(studentFormVO.getDirectionalState());
        if (baseMapper.updateById(student) > 0) {
            String operate = StudentConstants.DIRECTIONAL_STATE.equals(studentFormVO.getDirectionalState()) ? StudentConstants.RECORD_OPERATE_UNLOCK : StudentConstants.RECORD_OPERATE_LOCK;
            StudentRecord studentRecord = new StudentRecord(userId, student.getId(), StudentConstants.RECORD_TYPE_STUDENT, operate, studentFormVO.getSchoolContent());
            studentRecordService.save(studentRecord);

            return JsonResult.ok(operate + "成功");
        }

        return JsonResult.error("操作异常");
    }

    @Override
    public void exportStudent(PageParam<StudentExcelVO> page, HttpServletResponse response) {
        // 因为查询的是page接口 查询一个不可能的长度去查全部条数
        page.setSize(50000);

        // 导出数据源
        List<StudentExcelVO> studentExcelVOList = baseMapper.listExcel(page);

        // 如果导出文字 将数据进行转换
        if (StudentConstants.STUDENT_EXPORT_TEXT.equals(page.getString(StudentConstants.STUDENT_EXPORT_PARAM))) {
            Map<Object, Object> dictMap = dictService.getCacheDictMaps();
            for (StudentExcelVO student : studentExcelVOList) {
                student.setXb(dictService.cacheLabel(DictConstants.TYPE_XB, student.getXb(), dictMap));
                student.setXl(dictService.cacheLabel(DictConstants.TYPE_XL, student.getXl(), dictMap));
                student.setXw(dictService.cacheLabel(DictConstants.TYPE_XW, student.getXw(), dictMap));
                student.setXwlb(dictService.cacheLabel(DictConstants.TYPE_XWLB, student.getXwlb(), dictMap));
                student.setPyfs(dictService.cacheLabel(DictConstants.TYPE_PYFS, student.getPyfs(), dictMap));
                student.setSyszd(dictService.cacheLabel(DictConstants.TYPE_SYSZD, student.getSyszd(), dictMap));
                student.setZzmm(dictService.cacheLabel(DictConstants.TYPE_ZZMM, student.getZzmm(), dictMap));
                student.setHksfzrxx(dictService.cacheLabel(DictConstants.TYPE_HKSFZRXX, student.getHksfzrxx(), dictMap));
                student.setXjzt(dictService.cacheLabel(DictConstants.TYPE_XJZT, student.getXjzt(), dictMap));
                student.setJzbfdxbz(dictService.cacheLabel(DictConstants.TYPE_JZBFDXBZ, student.getJzbfdxbz(), dictMap));
                student.setKnslb(dictService.cacheLabel(DictConstants.TYPE_KNSLB, student.getKnslb(), dictMap));
                student.setMz(dictService.cacheLabel(DictConstants.TYPE_MZ, student.getMz(), dictMap));
                student.setZxjh(dictService.cacheLabel(DictConstants.TYPE_ZXJH, student.getZxjh(), dictMap));
                student.setDxDwszd(dictService.cacheLabel(DictConstants.TYPE_SYSZD, student.getDxDwszd(), dictMap));
                student.setDxDwxz(dictService.cacheLabel(DictConstants.COMPANY_NATURE, student.getDxDwxz(), dictMap));
                student.setDxDwhy(dictService.cacheLabel(DictConstants.COMPANY_INDUSTRY, student.getDxDwhy(), dictMap));
                student.setHyzk(dictService.cacheLabel(DictConstants.TYPE_HYZK, student.getHyzk(), dictMap));
                student.setFxxw(dictService.cacheLabel(DictConstants.TYPE_FXXW, student.getFxxw(), dictMap));
                student.setZxwyyz(dictService.cacheLabel(DictConstants.TYPE_ZXWYYZ, student.getZxwyyz(), dictMap));
                student.setBzkxl(dictService.cacheLabel(DictConstants.TYPE_BZKXL, student.getBzkxl(), dictMap));
                student.setBzkcc(dictService.cacheLabel(DictConstants.TYPE_BZKCC, student.getBzkcc(), dictMap));
                student.setYxdq(dictService.cacheLabel(DictConstants.TYPE_SYSZD, student.getYxdq(), dictMap));
                student.setYxdwxz(dictService.cacheLabel(DictConstants.TYPE_YXDWXZ, student.getYxdwxz(), dictMap));
                student.setYxdwhy(dictService.cacheLabel(DictConstants.TYPE_YXDWHY, student.getYxdwhy(), dictMap));
                student.setYxzwlb(dictService.cacheLabel(DictConstants.TYPE_YXZWLB, student.getYxzwlb(), dictMap));
                student.setYxyx(dictService.cacheLabel(DictConstants.TYPE_YXYX, student.getYxyx(), dictMap));
                student.setCxsydm(dictService.cacheLabel(DictConstants.TYPE_CXSYDM, student.getCxsydm(), dictMap));
                student.setXxfs(dictService.cacheLabel(DictConstants.TYPE_XXFS, student.getXxfs(), dictMap));
                student.setTks(StudentConstants.TKS_TRUE.equals(student.getTks())? "是" : "否");
            }
        }

        // 导出excel模板
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // 设置别名和排序
        excelAddHeaderAlias(writer);

        // 写出内容 xlsx
        writer.write(studentExcelVOList, true);

        // 设置列自适应宽 必须在write以后
        ExcelUtils.autoColumnMaxSizeAll(writer.getSheet());

        String fileName = "student-" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + ".xlsx";

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        try {
            OutputStream out = response.getOutputStream();
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } catch (IOException e) {
            writer.close();
            logger.error("导出失败 - StudentServiceImpl - exportStudent", e);
        } finally {
            writer.close();
        }

    }

    /**
     * 为导出对象设置别名和排序 排序顺序为add顺序
     *
     * @param writer ExcelWriter
     */
    public void excelAddHeaderAlias(ExcelWriter writer) {
        writer.addHeaderAlias("yearId", "毕业年份");
        writer.addHeaderAlias("xh", "学号");
        writer.addHeaderAlias("xm", "姓名");
        writer.addHeaderAlias("collegeName", "学院");
        writer.addHeaderAlias("collegeCode", "学院代码");
        writer.addHeaderAlias("majorName", "专业");
        writer.addHeaderAlias("majorCode", "专业代码");
        writer.addHeaderAlias("bjhm", "班级名称");
        writer.addHeaderAlias("xb", "性别");
        writer.addHeaderAlias("xl", "学历");
        writer.addHeaderAlias("xz", "学制");
        writer.addHeaderAlias("xw", "学位");
        writer.addHeaderAlias("xwlb", "学位类别");
        writer.addHeaderAlias("pyfs", "培养方式");
        writer.addHeaderAlias("rxsj", "入学时间");
        writer.addHeaderAlias("bysj", "毕业时间");
        writer.addHeaderAlias("syszd", "生源地区");
        writer.addHeaderAlias("sysf", "生源省份");
        writer.addHeaderAlias("sfzhm", "身份证号码");
        writer.addHeaderAlias("ksh", "考生号");
        writer.addHeaderAlias("zzmm", "政治面貌");
        writer.addHeaderAlias("mobile", "手机号码");
        writer.addHeaderAlias("email", "电子邮箱");
        writer.addHeaderAlias("hksfzrxx", "户口是否转入学校");
        writer.addHeaderAlias("xjzt", "学籍状态");
        writer.addHeaderAlias("csrq", "出生日期");
        writer.addHeaderAlias("jzbfdxbz", "精准帮扶对象标志");
        writer.addHeaderAlias("knslb", "困难生类别");
        writer.addHeaderAlias("mz", "民族");
        writer.addHeaderAlias("zxjh", "专项计划");
        writer.addHeaderAlias("dxhwpdw", "定向或委培单位");
        writer.addHeaderAlias("dxDwzzjgdm", "定向单位组织机构代码");
        writer.addHeaderAlias("dxDwxz", "定向单位性质");
        writer.addHeaderAlias("dxDwhy", "定向单位行业");
        writer.addHeaderAlias("dxDwszd", "定向单位所在地");
        writer.addHeaderAlias("dxDwlxr", "定向单位联系人");
        writer.addHeaderAlias("dxDwlxdh", "定向单位联系人电话");
        writer.addHeaderAlias("hyzk", "婚姻状况");
        writer.addHeaderAlias("yjfx", "研究方向");
        writer.addHeaderAlias("fxzy", "辅修专业");
        writer.addHeaderAlias("fxxw", "辅修学位");
        writer.addHeaderAlias("zxwyyz", "主修外语语种");
        writer.addHeaderAlias("jtdz", "家庭地址");
        writer.addHeaderAlias("jtyzbm", "家庭邮政编码");
        writer.addHeaderAlias("jjlxr", "紧急联系人");
        writer.addHeaderAlias("jjlxrdh", "紧急联系人电话");
        writer.addHeaderAlias("qq", "QQ");
        writer.addHeaderAlias("bzkxl", "本专科阶段学历类型");
        writer.addHeaderAlias("bzkcc", "本专科阶段院校层次");
        writer.addHeaderAlias("bzkyxmc", "本专科阶段院校名称");
        writer.addHeaderAlias("ahtc", "爱好特长");
        writer.addHeaderAlias("grjn", "个人技能");
        writer.addHeaderAlias("shsjjljrzqk", "社会实践经历及任职情况");
        writer.addHeaderAlias("hjjfbzpqk", "获奖及发表作品情况");
        writer.addHeaderAlias("zykyhdhxshd", "主要科研活动和学术活动");
        writer.addHeaderAlias("dstjyj", "导师推荐意见");
        writer.addHeaderAlias("grzjhqzyj", "个人自荐和求职意向");
        writer.addHeaderAlias("yxdq", "意向地区");
        writer.addHeaderAlias("yxdwxz", "意向单位性质");
        writer.addHeaderAlias("yxdwhy", "意向单位行业");
        writer.addHeaderAlias("yxzwlb", "意向职位类别");
        writer.addHeaderAlias("yxyx", "意向月薪");
        writer.addHeaderAlias("xyyj", "学院意见");
        writer.addHeaderAlias("cxsydm", "城乡生源");
        writer.addHeaderAlias("xxfs", "学习方式");
        writer.addHeaderAlias("bz", "备注");
        writer.addHeaderAlias("intenName", "就业意向-意向职位");
        writer.addHeaderAlias("intenAddress", "就业意向-意向工作地区");
        writer.addHeaderAlias("intenSalary", "就业意向-意向月薪");
        writer.addHeaderAlias("intenNature", "就业意向-意向单位性质");
        writer.addHeaderAlias("intenIndustry", "就业意向-意向单位行业");
        writer.addHeaderAlias("intenScale", "就业意向-意向单位规模");
        writer.addHeaderAlias("tks", "特困生");
    }

    /**
     * 验证学生表单
     *
     * @param studentFormVO 学生表单
     * @return 正常 code 200 否则 500
     */
    public JsonResult verifyStudentFormVO(StudentFormVO studentFormVO) {
        if (studentFormVO == null) {
            return JsonResult.error("参数异常");
        }

        if (studentFormVO == null) {
            return JsonResult.error("学生信息异常");
        }

        if (studentFormVO.getId() == null) {
            return JsonResult.error("学生主键异常");
        }

        return JsonResult.ok();
    }

    @Override
    public JsonResult studentSubmit(StudentFormVO studentFormVO, Integer loginUserId) {
        JsonResult verifyResult = verifyStudentFormVO(studentFormVO);
        if (Constants.RESULT_ERROR_CODE == verifyResult.getCode()) {
            return verifyResult;
        }

        Student student = new Student();
        BeanUtil.copyProperties(studentFormVO, student);

        StudentInfo studentInfo = new StudentInfo();
        BeanUtil.copyProperties(studentFormVO, studentInfo);
        studentInfo.setId(studentFormVO.getStudentInfoId());

        if (!student.getUserId().equals(loginUserId)) {
            return JsonResult.error("学生信息不匹配");
        }

        student.setStudentState(StudentConstants.STUDENT_STUDENT_SUBMIT);
        student.setCollegeState(StudentConstants.STUDENT_COLLEGE_WAIT);
        student.setSchoolState(StudentConstants.STUDENT_SCHOOL_WAIT);
        student.setCollegeContent("");
        student.setSchoolContent("");

        student.setDegree(setDegree(student.getXl()));
        baseMapper.updateById(student);
        studentInfoService.updateById(studentInfo);

        studentRecordService.save(
                new StudentRecord(loginUserId, student.getId(), StudentConstants.RECORD_TYPE_STUDENT, StudentConstants.RECORD_OPERATE_STUDENT_SUBMIT)
        );

        return JsonResult.ok();
    }

    @Override
    public JsonResult collegeSubmit(StudentFormVO studentFormVO, Integer loginUserId) {
        JsonResult verifyResult = verifyStudentFormVO(studentFormVO);
        if (Constants.RESULT_ERROR_CODE == verifyResult.getCode()) {
            return verifyResult;
        }

        Student student = new Student();
        BeanUtil.copyProperties(studentFormVO, student);

        StudentInfo studentInfo = new StudentInfo();
        BeanUtil.copyProperties(studentFormVO, studentInfo);
        studentInfo.setId(studentFormVO.getStudentInfoId());

        String operate = "";

        if (StudentConstants.STUDENT_COLLEGE_PASS.equals(student.getCollegeState())) {
            student.setStudentState(StudentConstants.STUDENT_STUDENT_SUBMIT);
            student.setSchoolState(StudentConstants.STUDENT_SCHOOL_PASS);
            operate = StudentConstants.RECORD_OPERATE_COLLEGE_PASS;
        }

        if (StudentConstants.STUDENT_COLLEGE_FAILED.equals(student.getCollegeState())) {
            student.setStudentState(StudentConstants.STUDENT_STUDENT_WAIT);
            student.setSchoolState(StudentConstants.STUDENT_SCHOOL_WAIT);
            operate = StudentConstants.RECORD_OPERATE_COLLEGE_FAILED;
        }

        student.setDegree(setDegree(student.getXl()));
        baseMapper.updateById(student);
        studentInfoService.updateById(studentInfo);

        studentRecordService.save(
                new StudentRecord(loginUserId, student.getId(), StudentConstants.RECORD_TYPE_STUDENT, operate, student.getCollegeContent())
        );

        return JsonResult.ok();
    }

    @Override
    public JsonResult schoolSubmit(StudentFormVO studentFormVO, Integer loginUserId) {
        if (studentFormVO == null) {
            return JsonResult.error("参数异常");
        }

        Student student = new Student();
        BeanUtil.copyProperties(studentFormVO, student);

        StudentInfo studentInfo = new StudentInfo();
        BeanUtil.copyProperties(studentFormVO, studentInfo);
        studentInfo.setId(studentFormVO.getStudentInfoId());

        String operate = "";

        if (StudentConstants.STUDENT_SCHOOL_PASS.equals(student.getSchoolState())) {
            student.setStudentState(StudentConstants.STUDENT_STUDENT_SUBMIT);
            student.setCollegeState(StudentConstants.STUDENT_COLLEGE_PASS);
            operate = StudentConstants.RECORD_OPERATE_SCHOOL_PASS;
        }

        if (StudentConstants.STUDENT_SCHOOL_FAILED.equals(student.getSchoolState())) {
            student.setStudentState(StudentConstants.STUDENT_STUDENT_WAIT);
            student.setCollegeState(StudentConstants.STUDENT_COLLEGE_WAIT);
            operate = StudentConstants.RECORD_OPERATE_SCHOOL_FAILED;
        }

        student.setDegree(setDegree(student.getXl()));

        if (student.getId() == null) {
            JsonResult jsonResult = verifyRepeat(student.getXh());
            if (Constants.RESULT_ERROR_CODE == jsonResult.getCode()) {
                return jsonResult;
            }

            User user = userService.saveOrUpdateStudent(student.getXh(), student.getXm());
            if (user == null) {
                return JsonResult.error("用户信息异常");
            }

            student.setFreeTermination(StudentConstants.FREE_TERMINATION_CLOSE);
            student.setUserId(user.getUserId());
            baseMapper.insert(student);
            studentInfo.setStudentId(student.getId());
            studentInfo.setUserId(student.getUserId());
            studentInfo.setXh(student.getXh());
            studentInfoService.save(studentInfo);
            operate = StrUtil.isBlank(operate) ? StudentConstants.RECORD_OPERATE_SCHOOL_ADD : operate + "(添加)";
        } else {
            baseMapper.updateById(student);
            studentInfoService.updateById(studentInfo);
            operate = StrUtil.isBlank(operate) ? StudentConstants.RECORD_OPERATE_SCHOOL_SUBMIT : operate;
        }

        studentRecordService.save(
                new StudentRecord(loginUserId, student.getId(), StudentConstants.RECORD_TYPE_STUDENT, operate, student.getSchoolContent())
        );

        return JsonResult.ok();
    }

    @Override
    public StudentIntenVO getStudentInten(Integer userId) {
        Student student = getByUserId(userId);

        StudentIntenVO studentIntenVO = new StudentIntenVO();

        if (student == null) {
            return studentIntenVO;
        }

        if (StrUtil.isBlank(student.getIntenName())) {
            studentIntenVO.setListIntenName(null);
        } else {
            studentIntenVO.setListIntenName(Arrays.asList(student.getIntenName().split(",")));
        }
        if (StrUtil.isBlank(student.getIntenAddress())) {
            studentIntenVO.setListIntenAddress(null);
        } else {
            studentIntenVO.setListIntenAddress(Arrays.asList(student.getIntenAddress().split(",")));
        }
        if (StrUtil.isBlank(student.getIntenNature())) {
            studentIntenVO.setListIntenNature(null);
        } else {
            studentIntenVO.setListIntenNature(Arrays.asList(student.getIntenNature().split(",")));
        }
        if (StrUtil.isBlank(student.getIntenIndustry())) {
            studentIntenVO.setListIntenIndustry(null);
        } else {
            studentIntenVO.setListIntenIndustry(Arrays.asList(student.getIntenIndustry().split(",")));
        }
        if (StrUtil.isBlank(student.getIntenScale())) {
            studentIntenVO.setListIntenScale(null);
        } else {
            studentIntenVO.setListIntenScale(Arrays.asList(student.getIntenScale().split(",")));
        }

        BeanUtil.copyProperties(student, studentIntenVO);

        // 查询学生简历
        StudentResume studentResume = studentResumeService.queryByStudentId(student.getId());

        if (StrUtil.isNotBlank(student.getXm())) {
            studentIntenVO.setStudentName(student.getXm());
        }
        // 出生日期
        if (student.getCsrq() != null) {
            studentIntenVO.setBirthday(DateUtil.format(student.getCsrq(), DatePattern.NORM_DATE_PATTERN));
        }
        if (StrUtil.isNotBlank(student.getXb())) {
            studentIntenVO.setStudentSex(dictService.cacheLabel(DictConstants.TYPE_XB, student.getXb()));
        }
        if (StrUtil.isNotBlank(student.getMobile())) {
            studentIntenVO.setStudentMobile(student.getMobile());
        }
        if (StrUtil.isNotBlank(student.getEmail())) {
            studentIntenVO.setStudentEmail(student.getEmail());
        }
        if (StrUtil.isNotBlank(student.getZzmm())) {
            studentIntenVO.setStudentPolitical(dictService.cacheLabel(DictConstants.TYPE_ZZMM, student.getZzmm()));
        }
        if (StrUtil.isNotBlank(student.getSyszd())) {
            studentIntenVO.setStudentAddress(dictService.cacheLabel(DictConstants.TYPE_SYSZD, student.getSyszd()));
        }
        // 如果学生填写简历
        if (studentResume != null) {
            StudentResumeVO studentResumeVO = new StudentResumeVO();
            BeanUtil.copyProperties(studentResume, studentResumeVO);
            studentIntenVO.setStudentResumeVO(studentResumeVO);
            QueryWrapper<StudentResumeItem> qr = new QueryWrapper<>();
            qr.eq("student_id", student.getId());
            List<StudentResumeItem> resumeItemList = studentResumeItemMapper.selectList(qr);
            if (!resumeItemList.isEmpty()) {
                List<StudentResumeItemVO> list = new ArrayList<>();
                for (StudentResumeItem item : resumeItemList) {
                    StudentResumeItemVO itemVO = new StudentResumeItemVO();
                    BeanUtil.copyProperties(item, itemVO);
                    list.add(itemVO);
                }
                studentIntenVO.setItemList(list);
            }
        }

        // 毕业去向意向
        List<StudentInten> intenList = studentIntenService.list(new LambdaQueryWrapper<StudentInten>()
                .eq(StudentInten::getStudentId, student.getId())
                .orderByAsc(StudentInten::getSort)
        );

        List<StudentInten> sxIntenList = intenList.stream().filter(d -> "升学(出国出境)".equals(d.getInten())).collect(Collectors.toList());
        for (StudentInten studentInten : sxIntenList) {
            List<Integer> sxList = new ArrayList<>();
            sxList.add(studentInten.getSxContinent());
            sxList.add(studentInten.getSxCountry());
            sxList.add(studentInten.getSxSchool());

            studentIntenVO.setSxMajor(studentInten.getSxMajor());
            switch (studentInten.getSort()) {
                case 1:
                    studentIntenVO.setSxQsTree1(sxList);
                    break;
                case 2:
                    studentIntenVO.setSxQsTree2(sxList);
                    break;
                case 3:
                    studentIntenVO.setSxQsTree3(sxList);
                    break;
            }
        }

        StudentInten kgInten = intenList.stream().filter(d -> "考公".equals(d.getInten())).findFirst().orElse(null);
        studentIntenVO.setKgType(kgInten != null ? kgInten.getKgType() : "");
        studentIntenVO.setKgProvince(kgInten != null ? kgInten.getKgProvince() : "");
        studentIntenVO.setKgCity(kgInten != null ? kgInten.getKgCity() : "");

        List<StudentInten> kyIntenList = intenList.stream().filter(d -> "考研".equals(d.getInten())).collect(Collectors.toList());
        if (kyIntenList.size() > 0) {
            List<String> kySchools = new ArrayList<>();
            String kyMajor = "";
            for (StudentInten studentInten : kyIntenList) {
                kySchools.add(studentInten.getKySchool());
                kyMajor = studentInten.getKyMajor();
            }
            studentIntenVO.setKySchools(kySchools);
            studentIntenVO.setKyMajor(kyMajor);
        }

        List<StudentInten> kbIntenList = intenList.stream().filter(d -> "考博".equals(d.getInten())).collect(Collectors.toList());
        if (kbIntenList.size() > 0) {
            List<String> kySchools = new ArrayList<>();
            String kyMajor = "";
            for (StudentInten studentInten : kbIntenList) {
                kySchools.add(studentInten.getKySchool());
                kyMajor = studentInten.getKyMajor();
            }
            studentIntenVO.setKySchools(kySchools);
            studentIntenVO.setKyMajor(kyMajor);
        }

        if (studentIntenVO.getStudentResumeVO() != null && !StrUtil.isBlank(studentIntenVO.getStudentResumeVO().getPhoto())) {
            String url = minioService.getPreSignedObjectUrl("resume", studentIntenVO.getStudentResumeVO().getPhoto());
            studentIntenVO.getStudentResumeVO().setPhotoPreview(url);
        }

        return studentIntenVO;
    }

    @Override
    public JsonResult updateStudentInten(StudentIntenVO studentIntenVO, Integer loginUserId) {
        if (studentIntenVO == null) {
            throw new ParameterException("参数错误");
        }

        if (studentIntenVO.getId() == null) {
            throw new ParameterException("主键参数错误");
        }

        studentIntenVO.setIntenName(CollUtil.join(studentIntenVO.getListIntenName(), ","));
        studentIntenVO.setIntenAddress(CollUtil.join(studentIntenVO.getListIntenAddress(), ","));
        studentIntenVO.setIntenNature(CollUtil.join(studentIntenVO.getListIntenNature(), ","));
        studentIntenVO.setIntenIndustry(CollUtil.join(studentIntenVO.getListIntenIndustry(), ","));
        studentIntenVO.setIntenScale(CollUtil.join(studentIntenVO.getListIntenScale(), ","));

        User user = userMapper.selectById(loginUserId);
        Student std = getByUserId(user.getUserId());

        studentIntenVO.setId(std.getId());

        Student student = new Student();

        BeanUtil.copyProperties(studentIntenVO, student);

        student.setQuestionnaireState(StudentConstants.STUDENT_QUESTIONNAIRE_SUBMIT);
        student.setInten(String.join(",", studentIntenVO.getInten()));

        // 判断学生是否选择自定模板简历
        if (StudentResumeConstants.RESUME_TYPE_NORMAL.equals(studentIntenVO.getResumeType())) {
            student.setResumeType(StudentResumeConstants.RESUME_TYPE_NORMAL);
        } else {
            student.setResumeType(StudentResumeConstants.RESUME_TYPE_CUSTOM);
        }

        if (updateById(student)) {
            // 标准化简历
            if (StudentResumeConstants.RESUME_TYPE_NORMAL.equals(studentIntenVO.getResumeType())) {
                // 保存学生简历
                StudentResumeVO studentResumeVO = studentIntenVO.getStudentResumeVO();
                studentResumeVO.setStudentId(student.getId());
                studentResumeVO.setList(studentIntenVO.getItemList());
                studentResumeService.saveResume(studentResumeVO);
            }

            // 保存就业毕业去向意向
            if (studentIntenVO.getInten().contains("升学(出国出境)")) {
                studentIntenService.remove(new LambdaQueryWrapper<StudentInten>()
                        .eq(StudentInten::getStudentId, student.getId())
                        .eq(StudentInten::getInten, "升学(出国出境)")
                );
                if (studentIntenVO.getSxQsTree1() != null) {
                    StudentInten studentInten = new StudentInten();
                    studentInten.setStudentId(student.getId());
                    studentInten.setInten("升学(出国出境)");
                    studentInten.setSxContinent(studentIntenVO.getSxQsTree1().get(0));
                    studentInten.setSxCountry(studentIntenVO.getSxQsTree1().get(1));
                    studentInten.setSxSchool(studentIntenVO.getSxQsTree1().get(2));
                    studentInten.setSxMajor(studentIntenVO.getSxMajor());
                    studentInten.setSort(1);

                    studentIntenService.save(studentInten);
                }
                if (studentIntenVO.getSxQsTree2() != null) {
                    StudentInten studentInten = new StudentInten();
                    studentInten.setStudentId(student.getId());
                    studentInten.setInten("升学(出国出境)");
                    studentInten.setSxContinent(studentIntenVO.getSxQsTree2().get(0));
                    studentInten.setSxCountry(studentIntenVO.getSxQsTree2().get(1));
                    studentInten.setSxSchool(studentIntenVO.getSxQsTree2().get(2));
                    studentInten.setSxMajor(studentIntenVO.getSxMajor());
                    studentInten.setSort(2);
                    studentIntenService.save(studentInten);
                }
                if (studentIntenVO.getSxQsTree3() != null) {
                    StudentInten studentInten = new StudentInten();
                    studentInten.setStudentId(student.getId());
                    studentInten.setInten("升学(出国出境)");
                    studentInten.setSxContinent(studentIntenVO.getSxQsTree3().get(0));
                    studentInten.setSxCountry(studentIntenVO.getSxQsTree3().get(1));
                    studentInten.setSxSchool(studentIntenVO.getSxQsTree3().get(2));
                    studentInten.setSxMajor(studentIntenVO.getSxMajor());
                    studentInten.setSort(3);
                    studentIntenService.save(studentInten);
                }
            }

            if (studentIntenVO.getInten().contains("考公")) {
                studentIntenService.remove(new LambdaQueryWrapper<StudentInten>()
                        .eq(StudentInten::getStudentId, student.getId())
                        .eq(StudentInten::getInten, "考公")
                );
                StudentInten studentInten = new StudentInten();
                studentInten.setStudentId(student.getId());
                studentInten.setInten("考公");
                studentInten.setKgType(studentIntenVO.getKgType());
                studentInten.setKgProvince(studentIntenVO.getKgProvince());
                studentInten.setKgCity(studentIntenVO.getKgCity());
                studentInten.setSort(1);
                studentIntenService.save(studentInten);
            }

            if (studentIntenVO.getInten().contains("考研")) {
                studentIntenService.remove(new LambdaQueryWrapper<StudentInten>()
                        .eq(StudentInten::getStudentId, student.getId())
                        .eq(StudentInten::getInten, "考研")
                );
                int i = 1;
                for (String school : studentIntenVO.getKySchools()) {
                    StudentInten studentInten = new StudentInten();
                    studentInten.setStudentId(student.getId());
                    studentInten.setInten("考研");
                    studentInten.setKySchool(school);
                    studentInten.setKyMajor(studentIntenVO.getKyMajor());
                    studentInten.setSort(i++);
                    studentIntenService.save(studentInten);
                }
            }

            if (studentIntenVO.getInten().contains("考博")) {
                studentIntenService.remove(new LambdaQueryWrapper<StudentInten>()
                        .eq(StudentInten::getStudentId, student.getId())
                        .eq(StudentInten::getInten, "考博")
                );
                int i = 1;
                for (String school : studentIntenVO.getKySchools()) {
                    StudentInten studentInten = new StudentInten();
                    studentInten.setStudentId(student.getId());
                    studentInten.setInten("考博");
                    studentInten.setKySchool(school);
                    studentInten.setKyMajor(studentIntenVO.getKyMajor());
                    studentInten.setSort(i++);
                    studentIntenService.save(studentInten);
                }
            }

            studentRecordService.save(new StudentRecord(loginUserId, student.getId(), StudentConstants.RECORD_TYPE_INTEN, StudentConstants.RECORD_OPERATE_STUDENT_INTEN)
            );
            return JsonResult.ok();
        }


        return JsonResult.error();
    }

    @Override
    public boolean updateSignCategory(String signCategory, Integer studentId) {
        Student student = new Student();
        student.setId(studentId);
        student.setSignCategory(signCategory);
        if (baseMapper.updateById(student) > 0) {
            return true;
        }
        return false;
    }

    @Override
    public void termination(Integer studentId) {
        Student student = baseMapper.selectById(studentId);
        student.setTermination(student.getTermination() != null ? student.getTermination() + 1 : 1);
        student.setSignCategory("");
        baseMapper.updateById(student);
    }

    @Override
    public List<Student> getStudentListByMajors(List<String> majors) {
        Year year = yearService.getYear();
        return baseMapper.getStudentListByMajors(majors, year.getId(), year.getId() - 1);
    }

    @Override
    public String setDegree(String xl) {
        // 结果默认等于本科
        String result = StudentConstants.STUDENT_DEGREE_BK;

        // 学历等于空或者等于本科 本研学历等于本科
        if (StrUtil.isBlank(xl) || StudentConstants.STUDENT_XL_BK.equals(xl)) {
            result = StudentConstants.STUDENT_DEGREE_BK;
        }

        // 学历等于硕士或者博士 本研学历等于研究生
        if (StudentConstants.STUDENT_XL_SS.equals(xl) || StudentConstants.STUDENT_XL_BS.equals(xl)) {
            result = StudentConstants.STUDENT_DEGREE_YJS;
        }

        return result;
    }

    @Override
    public List<StudentTitleVO> listStudentTitle(String collegeCode) {
        return baseMapper.listStudentTitle(collegeCode);
    }

    @Override
    public StudentFormVO getDetail(Integer id) {
        return baseMapper.getDetail(id);
    }

    @Override
    public List<Student> getStudentListByAbility(Map<String, Object> map) {
        Year year = yearService.getYear();
        map.put("yearId", year.getId());
        return baseMapper.getStudentListByAbility(map);
    }

    @Override
    public List<StudentSignStatusVO> listSignStatusPage(PageParam<StudentSignStatusVO> page) {
        return baseMapper.listSignStatusPage(page);
    }

    @Override
    public void updateStatus(Integer id, String status, String label, String content) {
        if (id == null) {
            return;
        }
        if (StrUtil.isBlank(label)) {
            return;
        }

        Student student = new Student();
        student.setId(id);
        student.setSignStatus(status);
        student.setSignStatusLabel(label);
        student.setSignStatusContent(content);
        updateById(student);
    }

    @Override
    public JsonResult updateStatus(StudentSignStatusVO studentSignStatusVO, Integer loginUserId) {
        if (null == studentSignStatusVO.getId()) {
            return JsonResult.error("参数异常");
        }

        Student student = new Student();
        student.setId(studentSignStatusVO.getId());
        student.setSignStatus(StudentConstants.SIGN_STATUS_MANUAL);
        student.setSignStatusLabel(studentSignStatusVO.getSignStatusLabel());
        student.setSignStatusContent(studentSignStatusVO.getSignStatusContent());
        student.setSignStatusProvince(studentSignStatusVO.getSignStatusProvince());
        student.setSignStatusProvinceTwo(studentSignStatusVO.getSignStatusProvinceTwo());
        student.setSignStatusIndustry(studentSignStatusVO.getSignStatusIndustry());
        student.setSignStatusIndustryTwo(studentSignStatusVO.getSignStatusIndustryTwo());
        student.setSignStatusContinent(studentSignStatusVO.getSignStatusContinent());
        student.setSignStatusCountry(studentSignStatusVO.getSignStatusCountry());
        student.setSignStatusSchool(studentSignStatusVO.getSignStatusSchool());
        student.setSignStatusContinentCode(studentSignStatusVO.getSignStatusContinentCode());
        student.setSignStatusCountryCode(studentSignStatusVO.getSignStatusCountryCode());
        student.setSignStatusSchoolCode(studentSignStatusVO.getSignStatusSchoolCode());
        student.setSignStatusMsg(studentSignStatusVO.getSignStatusMsg());

        if ("计划继续找工作".equals(student.getSignStatusLabel())) {
            student.setSignStatusContinent("");
            student.setSignStatusCountry("");
            student.setSignStatusSchool("");
            student.setSignStatusContinentCode(null);
            student.setSignStatusCountryCode(null);
            student.setSignStatusSchoolCode(null);
            student.setSignStatusMsg("");
        }

        if ("计划继续考公务员".equals(student.getSignStatusLabel())) {
            student.setSignStatusIndustry("");
            student.setSignStatusIndustryTwo("");
            student.setSignStatusContinent("");
            student.setSignStatusCountry("");
            student.setSignStatusSchool("");
            student.setSignStatusContinentCode(null);
            student.setSignStatusCountryCode(null);
            student.setSignStatusSchoolCode(null);
        }

        if ("升学(境内)".equals(student.getSignStatusLabel())) {
            student.setSignStatusProvince("");
            student.setSignStatusProvinceTwo("");
            student.setSignStatusIndustry("");
            student.setSignStatusIndustryTwo("");
            student.setSignStatusContinent("");
            student.setSignStatusCountry("");
            student.setSignStatusContinentCode(null);
            student.setSignStatusCountryCode(null);
            student.setSignStatusSchoolCode(null);
            student.setSignStatusMsg("");
        }

        if ("计划出国出境".equals(student.getSignStatusLabel())) {
            student.setSignStatusProvince("");
            student.setSignStatusProvinceTwo("");
            student.setSignStatusIndustry("");
            student.setSignStatusIndustryTwo("");
            student.setSignStatusMsg("");
        }

        if (updateById(student)) {
            studentRecordService.save(new StudentRecord(loginUserId, student.getId(), StudentConstants.RECORD_TYPE_STATUS, StudentConstants.RECORD_OPERATE_STATUS)
            );
            return JsonResult.ok("修改成功");
        } else {
            studentRecordService.save(new StudentRecord(loginUserId, student.getId(), StudentConstants.RECORD_TYPE_STATUS, StudentConstants.RECORD_OPERATE_STATUS + "(修改失败)")
            );
            return JsonResult.ok("修改失败");
        }
    }

    @Override
    public void exportStatusExcel(List<StudentSignStatusVO> list, HttpServletResponse response) {
        List<StudentStatusExcel> excelList = new ArrayList<>();
        for (StudentSignStatusVO item : list) {
            StudentStatusExcel excel = new StudentStatusExcel();
            BeanUtil.copyProperties(item, excel);
            excel.setDegree(StudentConstants.STUDENT_DEGREE_BK.equals(item.getDegree()) ? "本科" : "研究生");
            excelList.add(excel);
        }

        ExcelWriter writer = ExcelUtil.getWriter(true);

        excelAddHeaderAliasStatus(writer);

        writer.write(excelList, true);

        // 设置列自适应宽 必须在write以后
        ExcelUtils.autoColumnMaxSizeAll(writer.getSheet());

        String fileName = "status-" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + ".xlsx";

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        try {
            OutputStream out = response.getOutputStream();
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } catch (IOException e) {
            writer.close();
            logger.error("导出失败 - exportStatusExcel", e);
        } finally {
            writer.close();
        }
    }

    @Override
    public Map<String, List<Dict>> dictMap() {
        Map<String, List<Dict>> map = dictService.cacheMaps(StudentItentConstants.FORM_DICT_TYPES);
        Map<String, List<Dict>> maps = new HashMap<>();

        for (String key : map.keySet()) {
            List<Dict> listDict = map.get(key);
            List<Dict> listParent = new ArrayList<>();

            //将父级先存
            for (Dict dict : listDict) {
                //判断父级,若需要多级菜单只需更改if内判断条件
                if (dict.getParentId() != null && 0 == dict.getParentId()) {
                    Dict parent = new Dict();
                    parent.setValue(dict.getValue());
                    parent.setLabel(dict.getLabel());
                    parent.setId(dict.getId());
                    listParent.add(parent);
                }
            }

            //将子集包装存入父类
            for (Dict p : listParent) {
                List<Dict> childList = new ArrayList<>();
                for (Dict c : listDict) {
                    if (c.getParentId().equals(p.getId())) {
                        childList.add(c);
                    }
                }
                p.setChildren(childList);
            }
            maps.put(key, listParent);
        }
        return maps;
    }

    @Override
    public JsonResult temporaryStudentInten(StudentIntenVO studentIntenVO, Integer loginUserId) {
        if (studentIntenVO == null) {
            throw new ParameterException("参数错误");
        }

        if (studentIntenVO.getId() == null) {
            throw new ParameterException("主键参数错误");
        }

        studentIntenVO.setIntenName(CollUtil.join(studentIntenVO.getListIntenName(), ","));
        studentIntenVO.setIntenAddress(CollUtil.join(studentIntenVO.getListIntenAddress(), ","));
        studentIntenVO.setIntenNature(CollUtil.join(studentIntenVO.getListIntenNature(), ","));
        studentIntenVO.setIntenIndustry(CollUtil.join(studentIntenVO.getListIntenIndustry(), ","));
        studentIntenVO.setIntenScale(CollUtil.join(studentIntenVO.getListIntenScale(), ","));

        User user = userMapper.selectById(loginUserId);
        Student std = getByUserId(user.getUserId());

        studentIntenVO.setId(std.getId());

        Student student = new Student();

        BeanUtil.copyProperties(studentIntenVO, student);

        // 判断学生是否选择自定模板简历
        if (StudentResumeConstants.RESUME_TYPE_NORMAL.equals(studentIntenVO.getResumeType())) {
            student.setResumeType(StudentResumeConstants.RESUME_TYPE_NORMAL);
        } else {
            student.setResumeType(StudentResumeConstants.RESUME_TYPE_CUSTOM);
        }

        if (updateById(student)) {
            // 标准化简历
            if (StudentResumeConstants.RESUME_TYPE_NORMAL.equals(studentIntenVO.getResumeType())) {
                // 保存学生简历
                StudentResumeVO studentResumeVO = studentIntenVO.getStudentResumeVO();
                studentResumeVO.setStudentId(student.getId());
                studentResumeVO.setList(studentIntenVO.getItemList());
                studentResumeService.saveResume(studentResumeVO);
            }
            studentRecordService.save(new StudentRecord(loginUserId, student.getId(), StudentConstants.RECORD_TYPE_INTEN, StudentConstants.RECORD_OPERATE_STUDENT_INTEN)
            );
            return JsonResult.ok();
        }

        return JsonResult.error();
    }

    /**
     * 为导出对象设置别名和排序 排序顺序为add顺序
     *
     * @param writer ExcelWriter
     */
    public void excelAddHeaderAliasStatus(ExcelWriter writer) {
        writer.addHeaderAlias("yearId", "毕业年份");
        writer.addHeaderAlias("collegeName", "学院");
        writer.addHeaderAlias("majorName", "专业");
        writer.addHeaderAlias("bjhm", "班级");
        writer.addHeaderAlias("xh", "学号");
        writer.addHeaderAlias("xm", "姓名");
        writer.addHeaderAlias("degree", "学历");
        writer.addHeaderAlias("signStatusLabel", "就业状态");
        writer.addHeaderAlias("signStatusProvince", "意向省");
        writer.addHeaderAlias("signStatusProvinceTwo", "意向省二");
        writer.addHeaderAlias("signStatusIndustry", "意向行业");
        writer.addHeaderAlias("signStatusIndustryTwo", "意向行业二");
        writer.addHeaderAlias("signStatusMsg", "具体信息");
        writer.addHeaderAlias("signStatusContinent", "洲");
        writer.addHeaderAlias("signStatusCountry", "国家");
        writer.addHeaderAlias("signStatusSchool", "学校");
        writer.addHeaderAlias("signStatusContent", "就业状态备注");
    }

    @Override
    public JsonResult statisticsStudent(String yearId) {
        List<StudentStatistics> list = baseMapper.statisticsStudent(yearId);

        int count = 0;
        int questionnaire = 0;
        int questionnaireQz = 0;
        int questionnaireSx = 0;
        int questionnaireKg = 0;
        int questionnaireKy = 0;
        int student = 0;
        int college = 0;
        for (StudentStatistics item : list) {
            count += item.getCount();
            questionnaire += item.getQuestionnaire();
            questionnaireQz += item.getQuestionnaireQz();
            questionnaireSx += item.getQuestionnaireSx();
            questionnaireKg += item.getQuestionnaireKg();
            questionnaireKy += item.getQuestionnaireKy();
            student += item.getStudent();
            college += item.getCollege();
        }

        StudentStatistics statistics = new StudentStatistics();
        statistics.setCollegeName("总计");
        statistics.setCount(count);
        statistics.setQuestionnaire(questionnaire);
        statistics.setQuestionnaireQz(questionnaireQz);
        statistics.setQuestionnaireSx(questionnaireSx);
        statistics.setQuestionnaireKg(questionnaireKg);
        statistics.setQuestionnaireKy(questionnaireKy);
        statistics.setStudent(student);
        statistics.setCollege(college);

        list.add(0, statistics);

        return JsonResult.ok().setData(list);
    }

    @Override
    public JsonResult verifyRepeat(String xh) {
        List<Student> studentList = baseMapper.selectList(new QueryWrapper<Student>().eq("xh", xh));
        if (studentList.size() == 1 && studentList.get(0).getYearId() == null) {
            return JsonResult.ok("非毕业生").put("id", studentList.get(0).getId());
        }
        if (studentList.size() == 0) {
            return JsonResult.ok();
        }
        return JsonResult.error("学号“" + xh + "”已存在");
    }

    @Override
    public void changeSignEntry(Student student, Integer userId, String state) {
        if (student == null) {
            return;
        }

        if (state.equals(student.getSignEntry())) {
            return;
        }

        Student update = new Student();
        update.setId(student.getId());
        update.setSignEntry(state);
        baseMapper.updateById(update);

        String stateLabel = StudentConstants.SIGN_ENTRY_FALSE.equals(state) ? "关闭" : "开启";

        studentRecordService.save(
                new StudentRecord(userId, student.getId(), StudentConstants.RECORD_TYPE_SIGN, stateLabel + "忽略系统单位自主录入")
        );
    }

    @Override
    public JsonResult deleteStudent(String ids, Integer loginUserId) {
        if (StrUtil.isBlank(ids)) {
            return JsonResult.error("参数异常");
        }

        String[] idArr = ids.split(",");

        for (String id : idArr) {
            UpdateWrapper<Student> uw = new UpdateWrapper<>();
            uw.set("year_id", null);
            uw.lambda().eq(Student::getId, id);
            if (update(uw)) {
                studentRecordService.save(
                        new StudentRecord(loginUserId, Integer.parseInt(id), StudentConstants.RECORD_TYPE_STUDENT, StudentConstants.RECORD_OPERATE_STUDENT_DELETE)
                );
            } else {
                studentRecordService.save(
                        new StudentRecord(loginUserId, Integer.parseInt(id), StudentConstants.RECORD_TYPE_STUDENT, StudentConstants.RECORD_OPERATE_STUDENT_DELETE_FAIL)
                );
            }
        }

        return JsonResult.ok("删除成功");
    }

    @Override
    public List<StudentSignStatisticsCollegeVO> collegeStudentCount(Integer yearId, String xl, String tks) {
        return baseMapper.collegeStudentCount(yearId, xl, tks);
    }

    @Override
    public List<StudentSignStatisticsCollegeVO> majorStudentCount(Integer yearId, String xl) {
        return baseMapper.majorStudentCount(yearId, xl);
    }

    @Override
    public List<StudentSignStatisticsCollegeVO> mzStudentCount(Integer yearId, String xl, String tks) {
        return baseMapper.mzStudentCount(yearId, xl, tks);
    }

    @Override
    public List<StudentCollegeVO> studentCollegeList(Integer yearId) {
        return baseMapper.studentCollegeList(yearId);
    }

    @Override
    public void exportJob(PageParam<StudentExcelVO> page, HttpServletResponse response) {
        // 因为查询的是page接口 查询一个不可能的长度去查全部条数
        page.setSize(50000);

        // 导出数据源
        List<StudentExcelVO> studentExcelVOList = baseMapper.exportJob(page);

        // 如果导出文字 将数据进行转换

        Map<Object, Object> dictMap = dictService.getCacheDictMaps();
        for (StudentExcelVO student : studentExcelVOList) {
            student.setXb(dictService.cacheLabel(DictConstants.TYPE_XB, student.getXb(), dictMap));
            student.setXl(dictService.cacheLabel(DictConstants.TYPE_XL, student.getXl(), dictMap));
        }

        // 导出excel模板
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // 设置别名和排序
        writer.setOnlyAlias(true);
        excelAddHeaderAliasJob(writer);

        // 写出内容 xlsx
        writer.write(studentExcelVOList, true);

        // 设置列自适应宽 必须在write以后
        ExcelUtils.autoColumnMaxSizeAll(writer.getSheet());

        String fileName = "student-" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + ".xlsx";

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        try {
            OutputStream out = response.getOutputStream();
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } catch (IOException e) {
            writer.close();
            logger.error("导出失败 - StudentServiceImpl - exportStudent", e);
        } finally {
            writer.close();
        }
    }

    public void excelAddHeaderAliasJob(ExcelWriter writer) {
        writer.addHeaderAlias("yearId", "毕业年份");
        writer.addHeaderAlias("collegeName", "学院");
        writer.addHeaderAlias("majorName", "专业");
        writer.addHeaderAlias("xh", "学号");
        writer.addHeaderAlias("xm", "姓名");
        writer.addHeaderAlias("xb", "性别");
        writer.addHeaderAlias("degree", "学历");
        writer.addHeaderAlias("intenName", "意向职位名称");
        writer.addHeaderAlias("intenAddress", "意向工作地区");
        writer.addHeaderAlias("intenSalary", "意向岗位月薪");
        writer.addHeaderAlias("intenNature", "意向单位性质");
        writer.addHeaderAlias("intenIndustry", "意向单位行业");
        writer.addHeaderAlias("intenScale", "意向单位规模");
    }

    @Override
    public void exportGone(PageParam<StudentExcelVO> page, HttpServletResponse response) {
        // 因为查询的是page接口 查询一个不可能的长度去查全部条数
        page.setSize(50000);

        // 导出数据源
        List<StudentInten> studentList = baseMapper.exportGone(page);

        // 如果导出文字 将数据进行转换

        Map<Object, Object> dictMap = dictService.getCacheDictMaps();
        for (StudentInten student : studentList) {
            student.setXb(dictService.cacheLabel(DictConstants.TYPE_XB, student.getXb(), dictMap));
            student.setXl(dictService.cacheLabel(DictConstants.TYPE_XL, student.getXl(), dictMap));
        }

        // 导出excel模板
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // 设置别名和排序
        writer.setOnlyAlias(true);
        excelAddHeaderAliasGone(writer);

        // 写出内容 xlsx
        writer.write(studentList, true);

        // 设置列自适应宽 必须在write以后
        ExcelUtils.autoColumnMaxSizeAll(writer.getSheet());

        String fileName = "student-" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + ".xlsx";

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        try {
            OutputStream out = response.getOutputStream();
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } catch (IOException e) {
            writer.close();
            logger.error("导出失败 - StudentServiceImpl - exportStudent", e);
        } finally {
            writer.close();
        }
    }

    public void excelAddHeaderAliasGone(ExcelWriter writer) {
        writer.addHeaderAlias("yearId", "毕业年份");
        writer.addHeaderAlias("collegeName", "学院");
        writer.addHeaderAlias("majorName", "专业");
        writer.addHeaderAlias("xh", "学号");
        writer.addHeaderAlias("xm", "姓名");
        writer.addHeaderAlias("xb", "性别");
        writer.addHeaderAlias("degree", "学历");
        writer.addHeaderAlias("inten", "意向");
        writer.addHeaderAlias("sxContinentLabel", "升学(出国出境)意向洲");
        writer.addHeaderAlias("sxCountryLabel", "升学(出国出境)意向国家");
        writer.addHeaderAlias("sxSchoolLabel", "升学(出国出境)意向学校");
        writer.addHeaderAlias("sxMajor", "升学(出国出境)意向专业");
        writer.addHeaderAlias("kgType", "考公意向类型");
        writer.addHeaderAlias("kgProvince", "考公意向省份");
        writer.addHeaderAlias("kgCity", "考公意向城市");
        writer.addHeaderAlias("kySchool", "考研意向学校");
        writer.addHeaderAlias("kyMajor", "考研意向专业");
    }

    @Override
    public void updateFreeTermination(Integer id, Integer loginId) {
        Student student = baseMapper.selectById(id);
        if (student == null) {
            throw new BusinessException("没有找到学生");
        }

        String state = StudentConstants.FREE_TERMINATION_OPEN.equals(student.getFreeTermination()) ?
                StudentConstants.FREE_TERMINATION_CLOSE : StudentConstants.FREE_TERMINATION_OPEN;

        Student update = new Student();
        update.setId(student.getId());
        update.setFreeTermination(state);
        if (baseMapper.updateById(update) == 0) {
            throw new BusinessException("更新失败");
        }

        studentRecordService.save(
                new StudentRecord(loginId, id, StudentConstants.RECORD_TYPE_STUDENT, StudentConstants.getFreeTerminationName(state) + "自由解约")
        );

    }
}
